﻿using AppUpdate.Common;
using ConsoleHoster.Common.Model;
using ConsoleHoster.Common.Notifications;
using ConsoleHoster.Common.UserInput;
using ConsoleHoster.Common.Utilities;
using ConsoleHoster.Common.Utilities.IO;
using ConsoleHoster.Common.Utilities.Threading;
using ConsoleHoster.Model;
using ConsoleHoster.Model.Configuration;
using ConsoleHoster.Model.Entities;
using ConsoleHoster.Model.Plugins;
using ConsoleHoster.ViewModel;
using ConsoleHoster.ViewModel.Entities;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.IO.Packaging;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;

namespace ConsoleHoster.UnitTests.ViewModelTests
{
    [TestClass]
    public class ConsoleHostViewModelTests
    {
        private const int TaskCompletitionTimeout = 500000;

        private Mock<IDispatcher> mockDispatcher;
        private Mock<IProcessManager> mockProcessManager;
        private Mock<IConfigurationProvider> mockConfigurationProvider;
        private Mock<IUserInteractionManager> mockUserInteractionManager;
        private Mock<IUpdateManager> mockUpdateManager;
        private Mock<IKeyboardStateProvider> mockKeyboardStateProvider;
        private Mock<IKeyboardInputHandler> mockKeyboardInputHandler;
        private Mock<IFontSettingsProvider> mockFontSettingsProvider;
        private Mock<IGlobalCommandsProvider> mockGlobalCommandsProvider;
        private Mock<IProjectsManager> mockProjectsManager;
        private Mock<IImportLinkProvider> mockImportLinkProvider;
        private Mock<IStorageManager> mockStorageManager;
        private Mock<IFileSystemContentProvider> mockFileSystemProvider;
        private Mock<ISaveDestinationProvider> mockSaveDestinationProvider;
        private Mock<IFileProvider> mockFileProvider;
        private Mock<IPluginManager> mockPluginManager;
        private Mock<ILogger> mockLogger;
        private Mock<IWindowsShortcut> mockWindowsShortcut;
        private Mock<IProjectsFilter> mockProjectsFilter;
        private ConsoleHostViewModel hostVM;

        private TestRepository repository;

        [TestInitialize]
        public void Initialize()
        {
            // The following call forces PackUriHelper initalizer to initialize the "pack://" scheme
            string tmpForcingInitialization = PackUriHelper.UriSchemePack;

            this.mockDispatcher = new Mock<IDispatcher>();
            this.mockDispatcher
                .Setup(dp => dp.Invoke(It.IsAny<Action>(), It.IsAny<DispatcherPriority>()))
                .Callback<Action, DispatcherPriority>((a, dp) => a());

            this.mockProcessManager = new Mock<IProcessManager>();
            this.mockConfigurationProvider = new Mock<IConfigurationProvider>();
            this.mockUserInteractionManager = new Mock<IUserInteractionManager>();
            this.mockUpdateManager = new Mock<IUpdateManager>();
            this.mockKeyboardStateProvider = new Mock<IKeyboardStateProvider>();
            this.mockKeyboardInputHandler = new Mock<IKeyboardInputHandler>();
            this.mockFontSettingsProvider = new Mock<IFontSettingsProvider>();
            this.mockGlobalCommandsProvider = new Mock<IGlobalCommandsProvider>();
            this.mockProjectsManager = new Mock<IProjectsManager>();
            this.mockImportLinkProvider = new Mock<IImportLinkProvider>();
            this.mockStorageManager = new Mock<IStorageManager>();
            this.mockFileSystemProvider = new Mock<IFileSystemContentProvider>();
            this.mockSaveDestinationProvider = new Mock<ISaveDestinationProvider>();
            this.mockFileProvider = new Mock<IFileProvider>();
            this.mockPluginManager = new Mock<IPluginManager>();
            this.mockProjectsFilter = new Mock<IProjectsFilter>();
            this.mockLogger = new Mock<ILogger>();

            this.mockWindowsShortcut = new Mock<IWindowsShortcut>();
            this.mockWindowsShortcut.SetupProperty(sp => sp.WorkingDirectory);
            this.mockWindowsShortcut.SetupProperty(sp => sp.Target);
            this.mockWindowsShortcut.SetupProperty(sp => sp.Arguments);
            Func<IWindowsShortcut> mockShortcutFactory = () => this.WindowsShortcut;

            this.hostVM = new ConsoleHostViewModel(
                this.ConfigurationProvider,
                this.KeyboardInputHandler,
                this.UserInteractionManager,
                this.UpdateManager,
                this.KeyboardStateProvider,
                this.ProcessManager,
                this.FontSettingsProvider,
                this.GlobalCommandsProvider,
                this.ProjectsManager,
                this.ImportLinkProvider,
                this.StorageManager,
                this.PluginManager,
                this.FileSystemContentProvider,
                this.SaveDestinationProvider,
                this.FileProvider,
                this.ProjectsFilter,
                this.Dispatcher,
                this.Logger,
                mockShortcutFactory,
                name => EmptyLogger.Instance);

            this.repository = new TestRepository();
        }

        [TestMethod]
        public void NoAvailableProjectsWhenStarted()
        {
            Assert.AreEqual(0, this.hostVM.AvailableProjects.Count);
        }

        #region CreateNewProject tests
        [TestMethod]
        public async Task CreateNewProject_OpensProjectManagerWithNewProjectInTheList()
        {
            ProjectsListViewModel tmpVM = null;
            this.mockProjectsManager
                .Setup(pm => pm.ProvideData(It.IsAny<ProjectsListViewModel>()))
                .Callback<ProjectsListViewModel>(vm => { tmpVM = vm; });

            await this.hostVM.CreateNewProjectAsync();

            Assert.IsNotNull(tmpVM);
            Assert.AreEqual(1, tmpVM.Projects.Count);

            ConsoleProjectViewModel tmpProjectVM = tmpVM.Projects.Single().Project;
            Assert.AreEqual(ConsoleHostViewModel.DefaultExecutableName, tmpProjectVM.Executable);
            Assert.IsNotNull(tmpProjectVM.Commands, "Commands list is not initialized");
            Assert.AreEqual(0, tmpProjectVM.Commands.Count);
            Assert.AreEqual(ConsoleHostViewModel.NewProjectName, tmpProjectVM.Name);
        }

        [TestMethod]
        public async Task CreateNewProject_AddsTheNewProjectToTheAvailableProjectsList()
        {
            ConsoleProjectViewModel tmpConsoleVM = new ConsoleProjectViewModel(this.repository.ConsoleProject1);
            ProjectDetailsViewModel tmpDetailsVM = new ProjectDetailsViewModel(tmpConsoleVM, true, s => true, this.Dispatcher, this.Logger);
            ProjectsListViewModel tmpVM = new ProjectsListViewModel(new[] { tmpDetailsVM }, this.UserInteractionManager, this.Dispatcher, this.Logger);

            this.mockProjectsManager
                .Setup(pm => pm.ProvideData(It.IsAny<ProjectsListViewModel>()))
                .Returns(tmpVM);

            await this.hostVM.CreateNewProjectAsync();

            Assert.AreEqual(1, this.hostVM.AvailableProjects.Count);
            Assert.AreEqual(this.repository.ConsoleProject1, this.hostVM.AvailableProjects.Single().Model);
        }

        [TestMethod]
        public async Task CreateNewProject_PersistsTheReturnedProjectDetailsThroughTheStorageManager()
        {
            ConsoleProjectViewModel tmpConsoleVM = new ConsoleProjectViewModel(this.repository.ConsoleProject1);
            ProjectDetailsViewModel tmpDetailsVM = new ProjectDetailsViewModel(tmpConsoleVM, true, s => true, this.Dispatcher, this.Logger);
            ProjectsListViewModel tmpVM = new ProjectsListViewModel(new[] { tmpDetailsVM }, this.UserInteractionManager, this.Dispatcher, this.Logger);

            this.mockProjectsManager
                .Setup(pm => pm.ProvideData(It.IsAny<ProjectsListViewModel>()))
                .Returns(tmpVM);

            await this.hostVM.CreateNewProjectAsync();

            this.mockStorageManager.Verify(sm => sm.SaveProject(tmpConsoleVM.Model), Times.Once());
        }
        #endregion

        #region LoadAsync tests
        [TestMethod]
        public void LoadAsync_ChecksForUpdates()
        {
            Task tmpLoadTask = this.hostVM.LoadAsync();

            Assert.IsTrue(tmpLoadTask.Wait(TaskCompletitionTimeout));

            this.mockUpdateManager.Verify(um => um.CheckUpdateAvailability(It.IsAny<VersionInfo>()), Times.Once());
        }

        [TestMethod]
        public void LoadAsync_GetsProjectDetailsFromStorageManager()
        {
            Task tmpLoadTask = this.hostVM.LoadAsync();

            Assert.IsTrue(tmpLoadTask.Wait(TaskCompletitionTimeout));

            this.mockUpdateManager.Verify(um => um.CheckUpdateAvailability(It.IsAny<VersionInfo>()), Times.Once());
        }

        [TestMethod]
        public void LoadAsync_LoadsAllProjects()
        {
            ConsoleProject tmpProject = new ConsoleProject();
            ConsoleProject tmpAutoLoadProject = new ConsoleProject();
            this.mockStorageManager
                .Setup(sm => sm.LoadProjects(Constants.ProjectsFilename))
                .Returns(new[] { tmpProject, tmpAutoLoadProject });

            Task tmpLoadTask = this.hostVM.LoadAsync();

            Assert.IsTrue(tmpLoadTask.Wait(TaskCompletitionTimeout));

            Assert.AreEqual(2, this.hostVM.AvailableProjects.Count);
            Assert.IsTrue(this.hostVM.AvailableProjects.Any(item => item.Model == tmpProject));
            Assert.IsTrue(this.hostVM.AvailableProjects.Any(item => item.Model == tmpAutoLoadProject));
            Assert.AreEqual(0, this.hostVM.Projects.Count);
        }

        [TestMethod]
        public void LoadAsync_StartsAutoLoadProjects()
        {
            ConsoleProject tmpProject = new ConsoleProject()
            {
                Name = "Project 1"
            };
            ConsoleProject tmpAutoLoadProject = new ConsoleProject()
                {
                    Name = "Project2",
                    AutoLoad = true
                };
            this.mockStorageManager
                .Setup(sm => sm.LoadProjects(Constants.ProjectsFilename))
                .Returns(new[] { tmpProject, tmpAutoLoadProject });

            Task tmpLoadTask = this.hostVM.LoadAsync();

            Assert.IsTrue(tmpLoadTask.Wait(TaskCompletitionTimeout));

            Assert.AreEqual(2, this.hostVM.AvailableProjects.Count);
            Assert.IsTrue(this.hostVM.AvailableProjects.Any(item => item.Model == tmpProject));
            Assert.IsTrue(this.hostVM.AvailableProjects.Any(item => item.Model == tmpAutoLoadProject));

            Assert.AreEqual(1, this.hostVM.Projects.Count);
        }
        #endregion

        #region CheckForUpdates tests
        [TestMethod]
        public void CheckForUpdates_ChecksForUpdateAvailabilityThroughUpdateManager()
        {
            VersionInfo tmpCalledWithVI = null;
            this.mockUpdateManager
                .Setup(um => um.CheckUpdateAvailability(It.IsAny<VersionInfo>()))
                .Callback<VersionInfo>(vi => tmpCalledWithVI = vi);

            Task tmpUpdateTask;
            tmpUpdateTask = this.hostVM.CheckForUpdates();

            Assert.IsTrue(tmpUpdateTask.Wait(TaskCompletitionTimeout));

            this.mockUpdateManager.Verify(um => um.CheckUpdateAvailability(It.IsAny<VersionInfo>()), Times.Once());
            Assert.IsNotNull(tmpCalledWithVI);
            Assert.AreEqual(this.hostVM.CurrentAssemblyVersion, tmpCalledWithVI.Version);
        }

        [TestMethod]
        public void CheckForUpdates_RequestsUserConfirmationWhenUpdateIsAvailable()
        {
            InstallerPackageDetails tmpPackageDetails = new InstallerPackageDetails()
            {
                Version = new VersionInfo("some version info")
            };
            this.mockUpdateManager
                .Setup(um => um.CheckUpdateAvailability(It.IsAny<VersionInfo>()))
                .Returns(tmpPackageDetails);

            Task tmpUpdateTask;
            tmpUpdateTask = this.hostVM.CheckForUpdates();

            Assert.IsTrue(tmpUpdateTask.Wait(TaskCompletitionTimeout));
            Assert.AreEqual(tmpPackageDetails, this.hostVM.AvailableUpdateDetails);
            this.mockUserInteractionManager.Verify(im => im.ConfirmWithDetails(
                It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<string>(),
                It.IsAny<Func<ImageSource>>()),
                Times.Once());
        }

        [TestMethod]
        public void CheckForUpdates_StartsTheBrowserWithDownloadManagerPassedIn()
        {
            string tmpUri = "some uri";
            InstallerPackageDetails tmpPackageDetails = new InstallerPackageDetails()
            {
                Version = new VersionInfo("some version info"),
                DownloadUri = tmpUri
            };

            this.mockUpdateManager
                .Setup(um => um.CheckUpdateAvailability(It.IsAny<VersionInfo>()))
                .Returns(tmpPackageDetails);
            this.mockUserInteractionManager
                .Setup(im => im.ConfirmWithDetails(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Func<ImageSource>>()))
                .Returns(true);

            Task tmpUpdateTask;
            tmpUpdateTask = this.hostVM.CheckForUpdates();

            Assert.IsTrue(tmpUpdateTask.Wait(TaskCompletitionTimeout));
            this.mockProcessManager.Verify(pm => pm.StartProcess(tmpPackageDetails.DownloadUri), Times.Once());
        }
        #endregion

        #region StartProject tests
        [TestMethod]
        public async Task StartProject_AssignsProjectInstancesUniqueName()
        {
            string tmpProjectName = "Project1";
            ConsoleProject tmpProject = new ConsoleProject { Name = tmpProjectName };
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpProject);

            await this.hostVM.StartProjectAsync(tmpVM);
            await this.hostVM.StartProjectAsync(tmpVM);

            Assert.AreEqual(2, this.hostVM.Projects.Count);
            Assert.IsTrue(this.hostVM.Projects.Any(item => item.Name == GetProjectInstanceName(tmpProjectName, 0)));
            Assert.IsTrue(this.hostVM.Projects.Any(item => item.Name == GetProjectInstanceName(tmpProjectName, 1)));
        }

        [TestMethod]
        public async Task StartProject_SetsActiveProjectToTheGivenInstance()
        {
            string tmpProjectName = "Project1";
            ConsoleProject tmpProject = new ConsoleProject { Name = tmpProjectName };
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpProject);

            await this.hostVM.StartProjectAsync(tmpVM);

            Assert.IsNotNull(this.hostVM.ActiveConsole);
            Assert.AreEqual(tmpVM, this.hostVM.ActiveConsole.Project);
        }

        [TestMethod]
        public async Task StartProject_FillsInEmptyGapsInProjectInstancesNames()
        {
            string tmpProjectName = "Project1";
            ConsoleProject tmpProject = new ConsoleProject { Name = tmpProjectName };
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpProject);

            await this.hostVM.StartProjectAsync(tmpVM);
            await this.hostVM.StartProjectAsync(tmpVM);
            this.hostVM.Projects.Remove(this.hostVM.Projects.First(item => item.Name == GetProjectInstanceName(tmpProjectName, 0)));
            await this.hostVM.StartProjectAsync(tmpVM);

            Assert.AreEqual(2, this.hostVM.Projects.Count);
            Assert.IsTrue(this.hostVM.Projects.Any(item => item.Name == GetProjectInstanceName(tmpProjectName, 0)));
            Assert.IsTrue(this.hostVM.Projects.Any(item => item.Name == GetProjectInstanceName(tmpProjectName, 1)));
        }
        #endregion

        #region ImportProject tests
        [TestMethod]
        public void ImportProject_RetrievesLinkThroughImportLinkProvider()
        {
            this.hostVM.ImportShortcut();

            this.mockImportLinkProvider.Verify(ilp => ilp.GetShortcut(), Times.Once());
        }

        //[TestMethod]
        //public void ImportProject_RetrievesProjectDetailsForTheLinkThroughProjectDetailsProvider()
        //{
        //	ConsoleProjectViewModel tmpProjectVM = new ConsoleProjectViewModel();
        //	Mock<IWindowsShortcut> tmpMockShortcut = new Mock<IWindowsShortcut>();

        //	this.mockImportLinkProvider
        //		.Setup(ilp => ilp.GetShortcut())
        //		.Returns(tmpMockShortcut.Object);
        //	//this.mockProjectDetailsProvider
        //	//	.Setup(pdp => pdp.ProvideData(It.IsAny<ProjectDetailsViewModel>()))
        //	//	.Returns(tmpProjectVM);

        //	this.hostVM.ImportProject();

        //	//this.mockProjectDetailsProvider.Verify(pdp => pdp.ProvideData(It.IsAny<ProjectDetailsViewModel>()), Times.Once());

        //	Assert.AreEqual(1, this.hostVM.AvailableProjects.Count);
        //}
        #endregion

        #region ExportCurrentProject tests
        [TestMethod]
        public async Task ExportCurrentProject_RequestsForLocationToExportThroughSaveDestinationProvider()
        {
            const string tmpProjectName = "Project1";
            ConsoleProject tmpProject = new ConsoleProject { Name = tmpProjectName };
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpProject);

            await this.hostVM.StartProjectAsync(tmpVM);

            this.hostVM.ExportCurrentProjectShortcut();

            this.mockSaveDestinationProvider.Verify(dp => dp.ProvideData(ConsoleHostViewModel.GetNameForExportingShortcut(tmpProjectName)), Times.Once());
        }

        [TestMethod]
        public async Task ExportCurrentProject_SavesShortcutIfSaveDestinationProvided()
        {
            const string tmpProjectName = "Project1";
            ConsoleProject tmpProject = new ConsoleProject { Name = tmpProjectName };
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpProject);

            await this.hostVM.StartProjectAsync(tmpVM);

            const string tmpDestinationFile = "some file";
            this.mockSaveDestinationProvider
                .Setup(dp => dp.ProvideData(It.IsAny<string>()))
                .Returns(tmpDestinationFile);

            this.hostVM.ExportCurrentProjectShortcut();

            this.mockFileSystemProvider.Verify(fsp => fsp.ExportShortcut(this.WindowsShortcut, tmpDestinationFile));
        }

        [TestMethod]
        public async Task ExportCurrentProject_ConfiguresShortcutWithProjectData()
        {
            const string tmpProjectName = "Project1";
            const string tmpArguments = "some arguments";
            const string tmpWorkingDir = "working directory";
            const string tmpExecutable = "anyExe.cmd";

            ConsoleProject tmpProject = new ConsoleProject
            {
                Name = tmpProjectName,
                Arguments = tmpArguments,
                WorkingDir = tmpWorkingDir,
                Executable = tmpExecutable
            };
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpProject);

            await this.hostVM.StartProjectAsync(tmpVM);

            const string tmpDestinationFile = "some file";
            this.mockSaveDestinationProvider
                .Setup(dp => dp.ProvideData(It.IsAny<string>()))
                .Returns(tmpDestinationFile);

            this.hostVM.ExportCurrentProjectShortcut();

            Assert.AreEqual(tmpExecutable, this.WindowsShortcut.Target);
            Assert.AreEqual(tmpWorkingDir, this.WindowsShortcut.WorkingDirectory);
            Assert.AreEqual(tmpArguments, this.WindowsShortcut.Arguments);
        }

        [TestMethod]
        public void GetNameForExportingShortcut_ReturnsProperLinkName()
        {
            const string tmpProjectName = "some name";

            string tmpResult = ConsoleHostViewModel.GetNameForExportingShortcut(tmpProjectName);

            Assert.AreEqual(String.Format("{0}.lnk", tmpProjectName), tmpResult);
        }
        #endregion

        #region DuplicateCurrentProject tests
        [TestMethod]
        public async Task DuplicateCurrentProject_BringsUpProjectManagerWithADuplicatedProjectInstanceLoaded()
        {
            TestRepository tmpRepository = new TestRepository();
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpRepository.ConsoleProject1);

            ProjectsListViewModel tmpCalledWithVM = null;
            this.mockProjectsManager
                .Setup(pm => pm.ProvideData(It.IsAny<ProjectsListViewModel>()))
                .Callback<ProjectsListViewModel>(vm => tmpCalledWithVM = vm);

            this.hostVM.AvailableProjects.Add(tmpVM);
            await this.hostVM.StartProjectAsync(tmpVM);

            this.hostVM.DuplicateCurrentProject();

            Assert.IsNotNull(tmpCalledWithVM);
            Assert.AreEqual(2, tmpCalledWithVM.Projects.Count);
            Assert.IsTrue(tmpCalledWithVM.Projects.Any(item => item.Project.Name == tmpVM.Name));

            ProjectDetailsViewModel tmpDuplicateProject = tmpCalledWithVM.Projects.Where(item => item.Project.Name != tmpVM.Name).Single();

            Assert.AreEqual(ConsoleHostViewModel.GetDuplicateProjectName(tmpVM.Name, 0), tmpDuplicateProject.Project.Name);
        }
        #endregion

        #region Dispose tests
        [TestMethod]
        public async Task Dispose_ClosesAllActiveProjectInstances()
        {
            TestRepository tmpRepository = new TestRepository();
            ConsoleProjectViewModel tmpVM = new ConsoleProjectViewModel(tmpRepository.ConsoleProject1);
            await this.hostVM.StartProjectAsync(tmpVM);

            Assert.AreEqual(1, this.hostVM.Projects.Count);
            this.hostVM.Dispose();

            Assert.AreEqual(0, this.hostVM.Projects.Count);
        }
        #endregion

        #region Helper methods
        private static string GetProjectInstanceName(string argProjectName, int argIndex)
        {
            return String.Format("{0}_{1}", argProjectName, argIndex.ToString());
        }
        #endregion

        #region Properties
        private IDispatcher Dispatcher
        {
            get
            {
                return this.mockDispatcher.Object;
            }
        }

        private IProcessManager ProcessManager
        {
            get
            {
                return this.mockProcessManager.Object;
            }
        }

        private IConfigurationProvider ConfigurationProvider
        {
            get
            {
                return this.mockConfigurationProvider.Object;
            }
        }

        private IUserInteractionManager UserInteractionManager
        {
            get
            {
                return this.mockUserInteractionManager.Object;
            }
        }

        private IUpdateManager UpdateManager
        {
            get
            {
                return this.mockUpdateManager.Object;
            }
        }

        private IKeyboardStateProvider KeyboardStateProvider
        {
            get
            {
                return this.mockKeyboardStateProvider.Object;
            }
        }

        private IKeyboardInputHandler KeyboardInputHandler
        {
            get
            {
                return this.mockKeyboardInputHandler.Object;
            }
        }

        private IFontSettingsProvider FontSettingsProvider
        {
            get
            {
                return this.mockFontSettingsProvider.Object;
            }
        }

        private IGlobalCommandsProvider GlobalCommandsProvider
        {
            get
            {
                return this.mockGlobalCommandsProvider.Object;
            }
        }

        private IProjectsManager ProjectsManager
        {
            get
            {
                return this.mockProjectsManager.Object;
            }
        }

        private IImportLinkProvider ImportLinkProvider
        {
            get
            {
                return this.mockImportLinkProvider.Object;
            }
        }

        private IFileSystemContentProvider FileSystemContentProvider
        {
            get
            {
                return this.mockFileSystemProvider.Object;
            }
        }

        private IStorageManager StorageManager
        {
            get
            {
                return this.mockStorageManager.Object;
            }
        }

        private IPluginManager PluginManager
        {
            get
            {
                return this.mockPluginManager.Object;
            }
        }

        private ILogger Logger
        {
            get
            {
                return this.mockLogger.Object;
            }
        }

        private ISaveDestinationProvider SaveDestinationProvider
        {
            get
            {
                return this.mockSaveDestinationProvider.Object;
            }
        }

        public IWindowsShortcut WindowsShortcut
        {
            get
            {
                return this.mockWindowsShortcut.Object;
            }
        }

        public IProjectsFilter ProjectsFilter
        {
            get
            {
                return this.mockProjectsFilter.Object;
            }
        }

        public IFileProvider FileProvider
        {
            get
            {
                return this.mockFileProvider.Object;
            }
        }
        #endregion
    }
}
